package net.yxsoft.chainmaker;


import cn.hutool.json.JSONUtil;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.fastjson.JSONObject;
import com.google.protobuf.InvalidProtocolBufferException;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import io.grpc.stub.StreamObserver;
import net.yxsoft.kit.Helper;
import net.yxsoft.kit.rongzer.EncryptUtil;
import net.yxsoft.model.formdesigner.FnFormData;
import org.apache.log4j.Logger;
import org.bouncycastle.util.encoders.Hex;
import org.chainmaker.pb.common.ChainmakerBlock;
import org.chainmaker.pb.common.ChainmakerTransaction;
import org.chainmaker.pb.common.ResultOuterClass;

import java.sql.*;
import java.util.Date;
import java.util.List;

public class Subscribe extends InitClient implements Runnable {

    public static final Logger log = Logger.getLogger(EncryptUtil.class);

    private String sContactname;
    private String sTopic;

    public static final String YKC = "1";
    public static final String XGS = "2";

    public Subscribe(String sContactname, String sTopic) {
        this.sContactname = sContactname;
        this.sTopic = sTopic;
    }

    public void run() {
        testSubscribeBlock(this.sContactname, this.sTopic);
    }

    static public void testSubscribeBlock(String sContactname, String sTopic) {

        StreamObserver<ResultOuterClass.SubscribeResult> contractEventStreamObserver = new StreamObserver<ResultOuterClass.SubscribeResult>() {
            @Override
            public void onNext(ResultOuterClass.SubscribeResult result) {

                try {
                    ResultOuterClass.ContractEventInfoList contract = ResultOuterClass.ContractEventInfoList.parseFrom(result.getData());
                    int eventCount = contract.getContractEventsCount();
                    for (int i = 0; i < eventCount; i++) {
                        if (contract.getContractEvents(i).getTopic().equalsIgnoreCase("setsharedata")) {
                            System.out.print("\n第" + i + "个消息：");
                            System.out.print("\nChainId " + contract.getContractEvents(i).getChainId());
                            System.out.print("\nContractName " + contract.getContractEvents(i).getContractName());
                            System.out.print("\nTxId " + contract.getContractEvents(i).getTxId());
                            System.out.print("\nContractVersion " + contract.getContractEvents(i).getContractVersion());
                            System.out.print("\nBlockHeight " + contract.getContractEvents(i).getBlockHeight());
                            System.out.print("\nTopic " + contract.getContractEvents(i).getTopic());
                            int eventDataCount = contract.getContractEvents(i).getEventDataCount();
                            for (int j = 0; j < eventDataCount; j++) {
                                System.out.print("\nEventData " + j + "  " + contract.getContractEvents(i).getEventData(j));
                            }

                            String sTxId = contract.getContractEvents(i).getTxId();
                            String sBlockHeight = String.valueOf(contract.getContractEvents(i).getBlockHeight());
                            String orgid = contract.getContractEvents(i).getEventData(1);
                            String sData = contract.getContractEvents(i).getEventData(2);
                            String sAuth = contract.getContractEvents(i).getEventData(3);

                            // 将字符串转换为JsonArray
                            JSONObject shareObject = JSONUtil.toBean(sData, JSONObject.class);
                            JSONObject senderobj = shareObject.getJSONObject("Sender");
                            JSONObject receiverobj = shareObject.getJSONObject("Receiver");

                            FnFormData fnFormData = new FnFormData();

                            String sType = "";
                            String orderId = "";

                            String sName = "";
                            String sHash = "";
                            String sCreateTM = "";
                            String sRemark = "";

                            if (contract.getContractEvents(i).getEventData(0).equalsIgnoreCase("setOrderData")) {
                                orderId = shareObject.get("OrderId").toString();
                                sType = "指令数据";
                            } else if (contract.getContractEvents(i).getEventData(0).equalsIgnoreCase("setStateData")) {
                                orderId = shareObject.get("StateId").toString();
                                sType = "状态数据";
                            }
                            fnFormData.setAttrib31(orderId);
                            fnFormData.setAttrib40(contract.getContractEvents(i).getChainId());
                            fnFormData.setAttrib41(contract.getContractEvents(i).getContractName());
                            fnFormData.setAttrib42(contract.getContractEvents(i).getContractVersion());

//                            合约变量定义
//                            type BaseItem struct {
//                                Name     string
//                                Hash     string
//                                CreateTM uint64
//                                Remark   string
//                                TxHash   string
//                            }

                            if ((contract.getContractEvents(i).getEventData(0).equalsIgnoreCase("setOrderData") && sAuth.equals(YKC)) || (contract.getContractEvents(i).getEventData(0).equalsIgnoreCase("setStateData") && sAuth.equals(XGS))) {
                                sName = senderobj.get("Name").toString();
                                sHash = senderobj.get("Hash").toString();
                                sCreateTM = senderobj.get("CreateTM").toString();
                                sRemark = senderobj.get("Remark").toString();
                                fnFormData.setAttrib32(sName);
                                fnFormData.setAttrib12(sHash);
                                fnFormData.setAttrib33(sCreateTM);
                                fnFormData.setAttrib37(sRemark);
                                fnFormData.setAttrib58("");

                                fnFormData.setAttrib43(sTxId);
                                fnFormData.setAttrib44(sBlockHeight);
                                fnFormData.setAttrib45(orgid);
                            }

                            if ((contract.getContractEvents(i).getEventData(0).equalsIgnoreCase("setOrderData") && sAuth.equals(XGS)) || (contract.getContractEvents(i).getEventData(0).equalsIgnoreCase("setStateData") && sAuth.equals(YKC))) {
                                sName = receiverobj.get("Name").toString();
                                sHash = receiverobj.get("Hash").toString();
                                sCreateTM = receiverobj.get("CreateTM").toString();
                                sRemark = receiverobj.get("Remark").toString();
                                fnFormData.setAttrib35(sName);
                                fnFormData.setAttrib13(sHash);
                                fnFormData.setAttrib36(sCreateTM);
                                fnFormData.setAttrib38(sRemark);
                                fnFormData.setAttrib59("");

                                fnFormData.setAttrib46(sTxId);
                                fnFormData.setAttrib47(sBlockHeight);
                                fnFormData.setAttrib48(orgid);
                            }

                            //判断是否存在，如果存在，则更新，不存在则插入
                            Record rd = Db.findFirst("select * from fn_form_data where attrib_01 = ? and attrib_31 = ?", "273fc75a0c834f248203a272f8ca7840", orderId);

                            if (rd != null) {   //已经存在
                                if ((contract.getContractEvents(i).getEventData(0).equalsIgnoreCase("setOrderData") && sAuth.equals(YKC)) || (contract.getContractEvents(i).getEventData(0).equalsIgnoreCase("setStateData") && sAuth.equals(XGS))) {
                                    fnFormData.setConflictId(rd.getStr("conflict_id"));
                                    if (sName.equals(rd.getStr("attrib_35")) &&
                                            sHash.equals(rd.getStr("attrib_13")) &&
                                            sCreateTM.equals(rd.getStr("attrib_36")) &&
                                            sRemark.equals(rd.getStr("attrib_38"))) {
                                        fnFormData.setAttrib39("是");
                                    } else {
                                        fnFormData.setAttrib39("否");
                                    }
                                    if (!fnFormData.update()) {
                                        log.error("链上共享数据缓存保存失败，orderid: " + orderId);
                                    }
                                }

                                if ((contract.getContractEvents(i).getEventData(0).equalsIgnoreCase("setOrderData") && sAuth.equals(XGS)) || (contract.getContractEvents(i).getEventData(0).equalsIgnoreCase("setStateData") && sAuth.equals(YKC))) {
                                    fnFormData.setConflictId(rd.getStr("conflict_id"));
                                    if (sName.equals(rd.getStr("attrib_32")) &&
                                            sHash.equals(rd.getStr("attrib_12")) &&
                                            sCreateTM.equals(rd.getStr("attrib_33")) &&
                                            sRemark.equals(rd.getStr("attrib_37"))) {
                                        fnFormData.setAttrib39("是");
                                    } else {
                                        fnFormData.setAttrib39("否");
                                    }
                                    if (!fnFormData.update()) {
                                        log.error("链上共享数据缓存保存失败，orderid: " + orderId);
                                    }
                                }
                            } else {    //不存在
                                String cid = Helper.bulidUUID();
                                fnFormData.setConflictId(cid);
                                fnFormData.setRowId(cid);
                                fnFormData.setAttrib01("273fc75a0c834f248203a272f8ca7840");
                                fnFormData.setAttrib54(sType);   //共享数据动态表单
                                if ((contract.getContractEvents(i).getEventData(0).equalsIgnoreCase("setOrderData") && sAuth.equals(YKC)) || (contract.getContractEvents(i).getEventData(0).equalsIgnoreCase("setStateData") && sAuth.equals(XGS))) {   //插入发送方信息
                                    if (!fnFormData.save()) {
                                        log.error("链上共享数据缓存保存失败，orderid: " + orderId);
                                    }
                                }
                                if ((contract.getContractEvents(i).getEventData(0).equalsIgnoreCase("setOrderData") && sAuth.equals(XGS)) || (contract.getContractEvents(i).getEventData(0).equalsIgnoreCase("setStateData") && sAuth.equals(YKC))) {    //插入接收方信息
                                    if (!fnFormData.save()) {
                                        log.error("\n链上共享数据缓存保存失败，orderid: " + orderId);
                                    }
                                }
                            }
                        }

                        if (contract.getContractEvents(i).getTopic().equalsIgnoreCase("setevidencedata")) {
//                            合约变量定义
//                            type EvidenceData struct {
//                                EvdcHash     string
//                                Name         string
//                                CreateTM     uint64
//                                EvidenceType string
//                                Remark       string
//                                TxHash       string
//                            }
                            System.out.println("\n第" + i + "个消息：");
                            System.out.print("\nChainId " + contract.getContractEvents(i).getChainId());
                            System.out.print("\nContractName " + contract.getContractEvents(i).getContractName());
                            System.out.print("\nTxId " + contract.getContractEvents(i).getTxId());
                            System.out.print("\nContractVersion " + contract.getContractEvents(i).getContractVersion());
                            System.out.print("\nBlockHeight " + contract.getContractEvents(i).getBlockHeight());
                            System.out.print("\nTopic " + contract.getContractEvents(i).getTopic());
                            int eventDataCount = contract.getContractEvents(i).getEventDataCount();
                            for (int j = 0; j < eventDataCount; j++) {
                                System.out.print("\nEventData " + j + "  " + contract.getContractEvents(i).getEventData(j));
                            }

                            String sTxId = contract.getContractEvents(i).getTxId();
                            String sBlockHeight = String.valueOf(contract.getContractEvents(i).getBlockHeight());
                            String orgid = contract.getContractEvents(i).getEventData(1);
                            String sData = contract.getContractEvents(i).getEventData(2);

                            // 将字符串转换为JsonArray
                            JSONObject evidenceObject = JSONUtil.toBean(sData, JSONObject.class);

                            FnFormData fnFormData = new FnFormData();

                            String sEvdcHash = evidenceObject.get("EvdcHash").toString();
                            String sName = evidenceObject.get("Name").toString();
                            String sCreateTM = evidenceObject.get("CreateTM").toString();
                            String sEvidenceType = evidenceObject.get("EvidenceType").toString();
                            String sRemark = evidenceObject.get("Remark").toString();
                            String sTxHash = evidenceObject.get("TxHash").toString();

                            fnFormData.setAttrib12(sEvdcHash);
                            fnFormData.setAttrib32(sName);
                            fnFormData.setAttrib33(sCreateTM);
                            fnFormData.setAttrib04(sEvidenceType);
                            fnFormData.setAttrib37(sRemark);
                            fnFormData.setAttrib58(sTxHash);

                            fnFormData.setAttrib40(contract.getContractEvents(i).getChainId());
                            fnFormData.setAttrib41(contract.getContractEvents(i).getContractName());
                            fnFormData.setAttrib42(contract.getContractEvents(i).getContractVersion());

                            fnFormData.setAttrib43(sTxId);
                            fnFormData.setAttrib44(sBlockHeight);
                            fnFormData.setAttrib45(orgid);

                            String cid = Helper.bulidUUID();
                            fnFormData.setConflictId(cid);
                            fnFormData.setRowId(cid);
                            fnFormData.setAttrib01("080608a331c4435ba313a487beca105a");   //共享数据动态表单

                            if (!fnFormData.save()) {
                                log.error("\n链上存证数据缓存保存失败, evchash: " + sEvdcHash);
                            }
                        }
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onError(Throwable throwable) {
                // can add log here
            }

            @Override
            public void onCompleted() {
                // can add log here
            }
        };

        try {
            chainClient.subscribeContractEvent(-1, -1, sTopic, sContactname, contractEventStreamObserver);
//            chainClient.subscribeContractEvent(-1, -1, "setevidencedata", "evidence618", contractEventStreamObserver);
//            System.out.println("\n开始订阅合约信息: " + sContactname + " " + sTopic);
            Thread.sleep(100 * 1);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
